/*
 * TMap Designer - A Thematic Map design software
 * Copyright (C) 2006 World Health Organization
 * http://www.who.int
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA
 */
package who.tmap.ui.util;

import java.awt.BorderLayout;
import java.awt.Font;
import java.awt.Frame;
import java.awt.GraphicsEnvironment;
import java.awt.GridLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.WindowAdapter;
import java.awt.event.WindowEvent;

import javax.swing.BorderFactory;
import javax.swing.BoxLayout;
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JDialog;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JTextField;

import org.apache.log4j.Logger;

import who.tmap.bo.TextStyle;
import who.tmap.bo.BizObjects;
import who.tmap.bo.impl.BizObjectFactory;
import who.tmap.common.TMapException;

/**
 * A dialog to choose font and font style
 * @author stl
 */
public class JDialogFontChooser extends JDialog {

	public static enum Role { TEXT_INPUT, FONT_STYLE_ONLY };
	
    private static final String DEFAULT_FONT_NAME ="Serif";
    private static final String SAMPLE_TEXT ="The quick brown fox jumps over the lazy dog";
    
    private static Logger logger = Logger.getLogger(JDialogFontChooser.class);  
    
    private boolean okPressed =false;
    private String fontName;
    private int fontSize;
    private int fontStyle;
    private boolean bold;
    private boolean italic;
    private String text;
    private Role role;
    
	private JPanel jContentPane = null;
	private JDialogFontChooser thisDialog =this;

	private JPanel jPanelButton = null;
	private JButton jButtonOK = null;
	private JButton jButtonCancel = null;
	private JButton jButtonReset = null;
	private JPanel jPanelText = null;
	private JLabel jLabelText = null;
	private JTextField jTextFieldText = null;
	private JPanel jPanelProperties = null;
	private JLabel jLabel = null;
	private JComboBox jComboBoxFontName = null;
	private JLabel jLabelFontSize = null;
	private JComboBox jComboBoxFontSize = null;
	private JCheckBox jCheckBoxBold = null;
	private JCheckBox jCheckBoxItalic = null;
	
	
	/**
	 * This is the default constructor
	 */
	public JDialogFontChooser( Frame parent, boolean modal, Role role ) {
		super( parent, modal );
		this.role =role;
		initialize();
		
		resetUI();
		okPressed =false;
		
		setAlwaysOnTop( modal );
	}
	
	
	/**
	 * This method initializes this
	 * 
	 * @return void
	 */
	private void initialize() {
		this.setTitle( role == Role.TEXT_INPUT ? "Text input" : "Font style" );
		this.setSize(451, 252);
		this.setContentPane(getJContentPane());
		this.addWindowListener(new WindowAdapter() {
			public void windowActivated(WindowEvent e) {
				if ( getJTextFieldText().isEditable() ) {
					getJTextFieldText().requestFocusInWindow();
				}
			}
		});
		this.setLocationRelativeTo(null);
		
		getRootPane().setDefaultButton( getJButtonOK() );
	}
	/**
	 * This method initializes jContentPane
	 * 
	 * @return javax.swing.JPanel
	 */
	private javax.swing.JPanel getJContentPane() {
		if(jContentPane == null) {
			jContentPane = new JPanel();
			jContentPane.setLayout(new BorderLayout());
			jContentPane.add(getJPanelProperties(), BorderLayout.NORTH);
			jContentPane.add(getJPanelText(), BorderLayout.CENTER);
			jContentPane.add(getJPanelButton(), BorderLayout.SOUTH);
		}
		return jContentPane;
	}
	/**
	 * This method initializes jPanelButton	
	 * 	
	 * @return javax.swing.JPanel	
	 */    
	private JPanel getJPanelButton() {
		if (jPanelButton == null) {
			jPanelButton = new JPanel();
			jPanelButton.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
			jPanelButton.add(getJButtonOK(), null);
			jPanelButton.add(getJButtonCancel(), null);
			jPanelButton.add(getJButtonReset(), null);
		}
		return jPanelButton;
	}
	/**
	 * This method initializes jButtonOK	
	 * 	
	 * @return javax.swing.JButton	
	 */    
	private JButton getJButtonOK() {
		if (jButtonOK == null) {
			jButtonOK = new JButton();
			jButtonOK.setText("OK");
			jButtonOK.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {
					pressOK();
				}
			});
		}
		return jButtonOK;
	}
	
	private void pressOK() {
		if ( getJTextFieldText().getText().length() > 0 ) {
			okPressed =true;
	    
			retrieveValuesFromUI();
		} else {
			okPressed =false;
		}
	    
	    setVisible( false );		
	}
	/**
	 * This method initializes jButtonCancel	
	 * 	
	 * @return javax.swing.JButton	
	 */    
	private JButton getJButtonCancel() {
		if (jButtonCancel == null) {
			jButtonCancel = new JButton();
			jButtonCancel.setText("Cancel");
			jButtonCancel.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {
				    okPressed =false;
				    setVisible( false );
				}
			});
		}
		return jButtonCancel;
	}
	/**
	 * This method initializes jButtonReset	
	 * 	
	 * @return javax.swing.JButton	
	 */    
	private JButton getJButtonReset() {
		if (jButtonReset == null) {
			jButtonReset = new JButton();
			jButtonReset.setText("Reset");
			jButtonReset.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {    
				    resetUI();
				}
			});
		}
		return jButtonReset;
	}
	/**
	 * This method initializes jPanelText	
	 * 	
	 * @return javax.swing.JPanel	
	 */    
	private JPanel getJPanelText() {
		if (jPanelText == null) {
			jPanelText = new JPanel();		    
			jPanelText.setLayout(new BoxLayout(jPanelText, BoxLayout.Y_AXIS));
			jLabelText = new JLabel();
			jLabelText.setText( role == Role.TEXT_INPUT ? "Please input text below" : "Font sample below"  );
			jPanelText.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
			jPanelText.add(jLabelText, null);
			jPanelText.add(getJTextFieldText(), null);
		}
		return jPanelText;
	}
	/**
	 * This method initializes jTextFieldText	
	 * 	
	 * @return javax.swing.JTextField	
	 */    
	private JTextField getJTextFieldText() {
		if (jTextFieldText == null) {
			jTextFieldText = new JTextField();

			jTextFieldText.setEditable( role == Role.TEXT_INPUT );
			
			jTextFieldText.addKeyListener(new KeyAdapter() {   
				public void keyReleased(KeyEvent e) {    
				    thisDialog.setText( thisDialog.jTextFieldText.getText() );
				} 
			});

			jTextFieldText.addActionListener(new ActionListener() {
				public void actionPerformed(ActionEvent e) {
					pressOK();				
				}
			});
		}
		return jTextFieldText;
	}
	
	/**
	 * This method initializes jPanelProperties	
	 * 	
	 * @return javax.swing.JPanel	
	 */    
	private JPanel getJPanelProperties() {
		if (jPanelProperties == null) {
			jLabelFontSize = new JLabel();
			jLabel = new JLabel();
			jPanelProperties = new JPanel();
			
			jPanelProperties.setLayout( new GridLayout( 3, 2, 5, 5 ) );
			jPanelProperties.setBorder(BorderFactory.createEmptyBorder(5,5,5,5));
			jLabel.setText("Font name");
			jLabelFontSize.setText("Font size");
			jPanelProperties.add(jLabel, null);
			jPanelProperties.add(getJComboBoxFontName(), null);
			jPanelProperties.add(jLabelFontSize, null);
			jPanelProperties.add(getJComboBoxFontSize(), null);
			jPanelProperties.add(getJCheckBoxBold(), null);
			jPanelProperties.add(getJCheckBoxItalic(), null);
		}
		return jPanelProperties;
	}
	/**
	 * This method initializes jComboBoxFontName	
	 * 	
	 * @return javax.swing.JComboBox	
	 */    
	private JComboBox getJComboBoxFontName() {
		if (jComboBoxFontName == null) {
				
			GraphicsEnvironment gEnv =GraphicsEnvironment.getLocalGraphicsEnvironment();
			String envfonts[] = gEnv.getAvailableFontFamilyNames();
			
			jComboBoxFontName = new JComboBox( envfonts );			
			
			jComboBoxFontName.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {				    
				    setFontName( getJComboBoxFontName().getSelectedItem().toString() );
				    
				    displayText();
				}
			});
			
		}
		return jComboBoxFontName;
	}
	/**
	 * This method initializes jComboBoxFontSize	
	 * 	
	 * @return javax.swing.JComboBox	
	 */    
	private JComboBox getJComboBoxFontSize() {
		if (jComboBoxFontSize == null) {
			jComboBoxFontSize = new JComboBox();
			jComboBoxFontSize.setEditable(true);
			
			for( int size =8; size < 96; size+=2 ) {
			    jComboBoxFontSize.addItem( new MakeObj( String.valueOf( size ) ) );
			}
			
			jComboBoxFontSize.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {
				    setFontSize( Integer.parseInt( getJComboBoxFontSize().getSelectedItem().toString() ) );
				    
				    displayText();
				}
			});
		}
		return jComboBoxFontSize;
	}
	
	/**
	 * This method initializes jCheckBoxBold	
	 * 	
	 * @return javax.swing.JCheckBox	
	 */    
	private JCheckBox getJCheckBoxBold() {
		if (jCheckBoxBold == null) {
			jCheckBoxBold = new JCheckBox();
			jCheckBoxBold.setText("Bold");
			jCheckBoxBold.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {  
				    getFontStyleFromUI();
				    
				    displayText();
				}
			});
		}
		return jCheckBoxBold;
	}
	/**
	 * This method initializes jCheckBoxItalic	
	 * 	
	 * @return javax.swing.JCheckBox	
	 */    
	private JCheckBox getJCheckBoxItalic() {
		if (jCheckBoxItalic == null) {
			jCheckBoxItalic = new JCheckBox();
			jCheckBoxItalic.setText("Italic");
			jCheckBoxItalic.addActionListener(new ActionListener() { 
				public void actionPerformed(ActionEvent e) {
				    getFontStyleFromUI();
				    
				    displayText();
				}
			});
		} 
		return jCheckBoxItalic;
	}
	
	public void applyValuesToUI() {
	    getJComboBoxFontName().setSelectedItem( getFontName() );
	    getJComboBoxFontSize().setSelectedItem( new MakeObj( String.valueOf( getFontSize() ) ) );
	    getJCheckBoxBold().setSelected( isBold() );
	    getJCheckBoxItalic().setSelected( isItalic() );
	    
	    getJTextFieldText().setText( getText() );
	}
	
	private int getFontStyleFromUI() {
	    int fontStyle =Font.PLAIN;
	    if ( getJCheckBoxBold().isSelected() ) {
	        fontStyle+= Font.BOLD;
	    } 
	    
	    if ( getJCheckBoxItalic().isSelected() ) {
	        fontStyle+= Font.ITALIC;
	    }	
	    
	    setFontStyle( fontStyle );
	    
	    return fontStyle;
	}
	
	private void retrieveValuesFromUI() {
	    setFontName( getJComboBoxFontName().getSelectedItem().toString() );
	    setFontSize( Integer.parseInt( getJComboBoxFontSize().getSelectedItem().toString() ) );

	    getFontStyleFromUI();
	    
	    setText( getJTextFieldText().getText() );	    
	}
	
	public void displayText() {
	    
	    getJTextFieldText().setText( getText() );	    
	    
	    Font font =new Font( getFontName(), 
	            			 getFontStyle(), 
	            			 getFontSize() );
	    
	    getJTextFieldText().setFont( font );
	}
	
	public void resetUI() {
	    setFontName( DEFAULT_FONT_NAME );
	    setFontSize( 20 );
	    setFontStyle( Font.PLAIN );
	    setBold( false );
	    setItalic( false );
	    
	    if ( role == Role.FONT_STYLE_ONLY ) {
	    	setText( SAMPLE_TEXT );
	    }
	    
	    applyValuesToUI();
	    displayText();
	}
	
    /**
     * @return Returns the okPressed.
     */
    public boolean isOkPressed() {
        return okPressed;
    }
    
    /**
     * @return Returns the bold.
     */
    public boolean isBold() {
        return bold;
    }
    
    /**
     * @param bold The bold to set.
     */
    public void setBold(boolean bold) {
        this.bold = bold;
    }
    
    /**
     * @return Returns the fontName.
     */
    public String getFontName() {
        return fontName;
    }
    
    /**
     * @param fontName The fontName to set.
     */
    public void setFontName(String fontName) {
        this.fontName = fontName;
    }
    
    /**
     * @return Returns the fontStyle.
     */
    public int getFontStyle() {
        return fontStyle;
    }
    
    /**
     * @param fontStyle The fontStyle to set.
     */
    public void setFontStyle(int fontStyle) {
        this.fontStyle = fontStyle;
    }    
    
    /**
     * @return Returns the fontSize.
     */
    public int getFontSize() {
        return fontSize;
    }
    
    /**
     * @param fontSize The fontSize to set.
     */
    public void setFontSize(int fontSize) {
        this.fontSize = fontSize;
    }
    
    /**
     * @return Returns the italic.
     */
    public boolean isItalic() {
        return italic;
    }
    
    /**
     * @param italic The italic to set.
     */
    public void setItalic(boolean italic) {
        this.italic = italic;
    }
    
    /**
     * @return Returns the text.
     */
    public String getText() {
        return text;
    }
    
    /**
     * @param text The text to set.
     */
    public void setText(String text) {
        this.text = text;
    }
    
    private class MakeObj {
        private String item;
        
        public MakeObj( String item ) {
            this.item =item;
        }
        
        public String toString() {
            return item;
        }
    }
    
    public void applyStyle( TextStyle style ) {
    	setFontName( style.getFontName() );
    	setFontSize( style.getFontSize() );
    	setFontStyle( style.getFontStyle() );
    	
    	setBold( ( getFontStyle() & Font.BOLD ) > 0 );
    	setItalic( ( getFontStyle() & Font.ITALIC ) > 0 );
    }
    
    public TextStyle getStyle() {
    	TextStyle style =null;
		try {
			style = (TextStyle)BizObjectFactory.getInstance().get( BizObjects.TEXT_STYLE );
			
			style.setFontName( getFontName() );
			style.setFontSize( getFontSize() );
			style.setFontStyle( getFontStyleFromUI() );
		} catch (TMapException e) {
			logger.error( e );
		}
    	
    	return style;
    }
    
}  
